home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
C and C++
/
Graphics⁄Sound
/
RTrace-1.0-src
/
textrace.c
< prev
next >
Wrap
Text File
|
1992-09-06
|
25KB
|
1,266 lines
/*
* Copyright (c) 1992 Pedro Borges, Paulo Almeida, INESC-Norte.
* All rights reserved.
*
* This code received contributions from the following people:
*
* Roman Kuchkuda - basic ray tracer
* Mark VandeWettering - MTV ray tracer
* Augusto Sousa - overall, shading model
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Antonio Costa, at INESC-Norte. The name of the author and
* INESC-Norte may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "textrace.h"
/**********************************************************************
* RAY TRACING - Version 7.3.2 *
* *
* MADE BY: Pedro Borges, Paulo Almeida, INESC-Norte, June 1992 *
* MODIFIED BY: Antonio Costa, INESC-Norte, August 1992 *
**********************************************************************/
#ifndef __STDC__
#define ERR_MAX 16
#endif
static void
vcpy(u, v)
xyz_ptr u, v;
{
u->x = v->x;
u->y = v->y;
u->z = v->z;
}
static void
vadd(u, v, w)
xyz_ptr u, v, w;
{
u->x = v->x + w->x;
u->y = v->y + w->y;
u->z = v->z + w->z;
}
static void
vsub(u, v, w)
xyz_ptr u, v, w;
{
u->x = v->x - w->x;
u->y = v->y - w->y;
u->z = v->z - w->z;
}
static void
vmul(u, v, r)
xyz_ptr u, v;
real r;
{
u->x = v->x * r;
u->y = v->y * r;
u->z = v->z * r;
}
static void
vmuladd(u, v, r)
xyz_ptr u, v;
real r;
{
u->x += v->x * r;
u->y += v->y * r;
u->z += v->z * r;
}
static void
vtransf(u, ax, v)
xyz_ptr u;
xyz_axes *ax;
xyz_ptr v;
{
vmul(u, &ax->x_v, v->x);
vmuladd(u, &ax->y_v, v->y);
vmuladd(u, &ax->z_v, v->z);
}
static void
vminmax(min, max, v)
xyz_ptr min, max, v;
{
if (v->x < min->x)
min->x = v->x;
else if (v->x > max->x)
max->x = v->x;
if (v->y < min->y)
min->y = v->y;
else if (v->y > max->y)
max->y = v->y;
if (v->z < min->z)
min->z = v->z;
else if (v->z > max->z)
max->z = v->z;
}
real
vpint(u, v)
xyz_ptr u, v;
{
return u->x * v->x + u->y * v->y + u->z * v->z;
}
real
vmod(v)
xyz_ptr v;
{
return sqrt(v->x * v->x + v->y * v->y + v->z * v->z);
}
int
vnormalize(v)
xyz_ptr v;
{
real r;
r = vmod(v);
if (r < TINY)
return 0;
vmul(v, v, 1.0 / r);
return 1;
}
real
vinvmat(x, y, z, ox, oy, oz)
xyz_ptr x, y, z, ox, oy, oz;
{
real det, idet;
ox->x = y->y * z->z - y->z * z->y;
oy->x = y->z * z->x - y->x * z->z;
oz->x = y->x * z->y - y->y * z->x;
det = x->x * ox->x + x->y * oy->x + x->z * oz->x;
if (fabs(det) < TINY)
return 0.0;
ox->y = x->z * z->y - x->y * z->z;
oy->y = x->x * z->z - x->z * z->x;
oz->y = x->y * z->x - x->x * z->y;
ox->z = x->y * y->z - x->z * y->y;
oy->z = x->z * y->x - x->x * y->z;
oz->z = x->x * y->y - x->y * y->x;
idet = 1 / det;
vmul(ox, ox, idet);
vmul(oy, oy, idet);
vmul(oz, oz, idet);
return det;
}
static int
err_line(fp)
FILE *fp;
{
int pos, nl, i;
nl = 1;
pos = ftell(fp);
rewind(fp);
for (i = 0; i < pos - 1; i++)
if (getc(fp) == '\n')
nl++;
return nl;
}
static void
prt_arr(s)
char *s[];
{
while (*s)
fprintf(stderr, "%s", *s++);
fprintf(stderr, "\n");
}
static void
errorfn(s, fp, fn)
char *s[];
FILE *fp;
char *fn;
{
fprintf(stderr, "Text error in %s file at line %d: ", fn, err_line(fp));
prt_arr(s);
exit(1);
}
static void
error(s)
char *s[];
{
fprintf(stderr, "Text error: ");
prt_arr(s);
exit(1);
}
void *
alloc(t)
unsigned t;
{
void *p;
#ifdef __STDC__
char *err[] =
{"Memory allocation error ", 0};
#else
char *err[ERR_MAX];
err[0] = "Memory allocation error ";
err[1] = 0;
#endif
p = (void *) malloc(t);
if (!p)
error(err);
return p;
}
static FILE *
cfopen(file, mode)
char *file, *mode;
{
FILE *fp;
#ifdef __STDC__
char *err[] =
{"Open error in file ", 0, 0};
#else
char *err[ERR_MAX];
err[0] = "Open error in file ";
err[1] = 0;
err[2] = 0;
#endif
fp = fopen(file, mode);
if (!fp)
{
err[1] = file;
error(err);
}
return fp;
}
/***** Global variables *****/
static file_ptr fp;
static xyz_axes *orient_ptr = 0;
static xyz_ptr size_ptr = 0;
static real space = NULSP;
static font *fonts_ptr = 0, *font_ptr = 0;
static code *code_ptr = 0;
static char *codename = 0;
static char buffer[BUFFERSIZE];
static char ifname[] = "input";
static void
skip_space(fp)
FILE *fp;
{
int c;
do
{
c = getc(fp);
} while (isspace(c));
ungetc(c, fp);
}
static void
expect(s, fp, fname)
char *s;
FILE *fp;
char *fname;
{
char b[100];
int i;
#ifdef __STDC__
char *err[] =
{"Expected '", 0, "', found '", 0, "'", 0};
#else
char *err[ERR_MAX];
err[0] = "Expected '";
err[1] = 0;
err[2] = "', found '";
err[3] = 0;
err[4] = "'";
err[5] = 0;
#endif
i = 0;
skip_space(fp);
while (s[i])
{
if ((b[i] = getc(fp)) != s[i])
{
b[++i] = 0;
err[1] = s;
err[3] = b;
errorfn(err, fp, fname);
}
i++;
}
}
static char *
get_ident(fp, fname)
FILE *fp;
char *fname;
{
char *b;
int c, i;
#ifdef __STDC__
char *err[] =
{"Character name too long", 0};
#else
char *err[ERR_MAX];
err[0] = "Character name too long";
err[1] = 0;
#endif
b = buffer;
skip_space(fp);
i = 0;
while (c = getc(fp), !isspace(c) && c != EOF && i < BUFFERSIZE - 1)
b[i++] = c;
if (i == BUFFERSIZE - 1)
errorfn(err, fp, fname);
b[i] = 0;
return b;
}
static real
get_real(fp, fname)
FILE *fp;
char *fname;
{
real r;
#ifdef __STDC__
char *err[] =
{"Real number expected", 0};
#else
char *err[ERR_MAX];
err[0] = "Real number expected";
err[1] = 0;
#endif
if (fscanf(fp, REALCONV, &r) < 1)
errorfn(err, fp, fname);
return r;
}
static int
get_int(fp, fname)
FILE *fp;
char *fname;
{
int i;
#ifdef __STDC__
char *err[] =
{"Integer expected", 0};
#else
char *err[ERR_MAX];
err[0] = "Integer expected";
err[1] = 0;
#endif
if (fscanf(fp, "%d", &i) < 1)
errorfn(err, fp, fname);
return i;
}
static void
get_vector(vec_ptr)
xyz_ptr vec_ptr;
{
vec_ptr->x = get_real(fp, ifname);
vec_ptr->y = get_real(fp, ifname);
vec_ptr->z = get_real(fp, ifname);
}
static char *
get_name_from_code(c)
int c;
{
code *cp;
char a[10];
#ifdef __STDC__
char *err[] =
{"Character code ", 0, " missing in encoding file ", 0, 0};
#else
char *err[ERR_MAX];
err[0] = "Character code ";
err[1] = 0;
err[2] = " missing in encoding file ";
err[3] = 0;
err[4] = 0;
#endif
cp = code_ptr;
while (cp && cp->code != c)
cp = cp->next;
if (!cp)
{
err[3] = codename;
sprintf(a, "%d", c);
err[1] = a;
error(err);
}
return cp->name;
}
static char *
get_name_from_file()
{
char *b;
int c, i;
#ifdef __STDC__
char *err1[] =
{"End of file unexpected", 0};
char *err2[] =
{"Character name too long", 0};
#else
char *err1[ERR_MAX];
char *err2[ERR_MAX];
err1[0] = "End of file unexpected";
err1[1] = 0;
err2[0] = "Character name too long";
err2[1] = 0;
#endif
b = buffer;
i = 0;
while (c = getc(fp), c != PSNAME && c != EOF && i < BUFFERSIZE - 1)
b[i++] = c;
if (c == EOF)
errorfn(err1, fp, ifname);
if (i == BUFFERSIZE - 1)
errorfn(err2, fp, ifname);
b[i] = 0;
return b;
}
static void
get_char_desc(pdp, fp, fname)
prismdsc *pdp;
FILE *fp;
char *fname;
{
int ncc, nc, cc, c;
ccurve *cca;
curve *ca;
char *type;
#ifdef __STDC__
char *err[] =
{"Unknown curve type in font file", 0};
#else
char *err[ERR_MAX];
err[0] = "Unknown curve type in font file";
err[1] = 0;
#endif
pdp->bot = get_real(fp, fname);
pdp->top = get_real(fp, fname);
pdp->width = get_real(fp, fname);
ncc = pdp->n = get_int(fp, fname);
cca = pdp->ccurve_arr = newa(ccurve, ncc);
for (cc = 0; cc < ncc; cc++)
{
nc = cca[cc].n = get_int(fp, fname);
ca = cca[cc].curve_arr = newa(curve, nc + 1);
for (c = 0; c < nc; c++)
{
type = get_ident(fp, fname);
if (!strcmp(type, "l"))
{
ca[c].t = 1;
ca[c].p[0].x = get_real(fp, fname);
ca[c].p[0].y = get_real(fp, fname);
} else if (!strcmp(type, "c"))
{
ca[c].t = 3;
ca[c].p[0].x = get_real(fp, fname);
ca[c].p[0].y = get_real(fp, fname);
ca[c].p[1].x = get_real(fp, fname);
ca[c].p[1].y = get_real(fp, fname);
ca[c].p[2].x = get_real(fp, fname);
ca[c].p[2].y = get_real(fp, fname);
} else
errorfn(err, fp, fname);
}
ca[nc].p[0].x = ca[0].p[0].x;
ca[nc].p[0].y = ca[0].p[0].y;
}
}
static void
get_char_font(chp)
character *chp;
{
font *fntp;
FILE *fp;
char *name;
int c;
#ifdef __STDC__
char *err1[] =
{"Unexpected character in font file", 0};
char *err2[] =
{"Missing character description of '", 0,
"' in font file ", 0, 0};
#else
char *err1[ERR_MAX];
char *err2[ERR_MAX];
err1[0] = "Unexpected character in font file";
err1[1] = 0;
err2[0] = "Missing character description of '";
err2[1] = 0;
err2[2] = "' in font file ";
err2[3] = 0;
err2[4] = 0;
#endif
fntp = font_ptr;
err2[1] = chp->name;
err2[3] = fntp->name;
fp = cfopen(fntp->name, "r");
while (1)
{
skip_space(fp);
c = getc(fp);
if (c == EOF)
error(err2);
if (c != PSNAME)
errorfn(err1, fp, fntp->name);
name = get_ident(fp, fntp->name);
if (strcmp(name, chp->name))
{
while (c = getc(fp), c != PSNAME && c != EOF)
;
if (c == EOF)
error(err2);
ungetc(c, fp);
} else
{
get_char_desc(chp->prismdsc_ptr, fp, fntp->name);
fclose(fp);
break;
}
}
}
static prismdsc *
get_prismdsc_ptr(name)
char *name;
{
character *chp;
chp = font_ptr->ch_ptr;
while (chp && strcmp(name, chp->name))
chp = chp->next;
if (!chp)
{
chp = new(character);
chp->next = font_ptr->ch_ptr;
font_ptr->ch_ptr = chp;
chp->name = alloc(strlen(name) + 1);
strcpy(chp->name, name);
chp->prismdsc_ptr = new(prismdsc);
get_char_font(chp);
}
return chp->prismdsc_ptr;
}
static void
calc_englob(pp, minp, maxp)
prism *pp;
xyz_ptr minp, maxp;
{
prismdsc *pdp;
xyz_struct v[2], u, w;
int i, j, k;
pdp = pp->prismdsc_ptr;
v[0].x = 0.0;
v[1].x = pdp->width * pp->size_ptr->x;
v[0].y = pdp->bot * pp->size_ptr->y;
v[1].y = pdp->top * pp->size_ptr->y;
v[0].z = 0.0;
v[1].z = pp->size_ptr->z;
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
for (k = 0; k < 2; k++)
{
u.x = v[i].x;
u.y = v[j].y;
u.z = v[k].z;
vtransf(&w, pp->orient_ptr, &u);
if (!i && !j && !k)
{
vcpy(minp, &w);
vcpy(maxp, &w);
} else
vminmax(minp, maxp, &w);
}
vadd(minp, minp, &pp->position);
vadd(maxp, maxp, &pp->position);
}
static void
update_position(posp, width)
xyz_ptr posp;
real width;
{
real size;
size = size_ptr->x;
size *= width + space;
vmuladd(posp, &orient_ptr->x_v, size);
}
static void
get_at_text()
{
prism *prism_ptr;
void **priv_p_p;
xyz_struct position;
xyz_ptr minp, maxp;
char *name;
int c;
get_vector(&position);
expect("\"", fp, ifname);
while (c = getc(fp), c != '\"')
{
if (c == ' ')
{
update_position(&position, 0.5);
continue;
}
prism_ptr = new(prism);
priv_p_p = (void **) create_pp_obj(&minp, &maxp);
*priv_p_p = (void *) prism_ptr;
if (c != PSNAME)
name = get_name_from_code(c);
else
name = get_name_from_file();
prism_ptr->prismdsc_ptr = get_prismdsc_ptr(name);
prism_ptr->position = position;
prism_ptr->orient_ptr = orient_ptr;
prism_ptr->size_ptr = size_ptr;
calc_englob(prism_ptr, minp, maxp);
update_position(&position, prism_ptr->prismdsc_ptr->width);
#ifdef THINK_C
/* On the mac, we need to track reading of text objects on the progress bar */
if (status_dialog_visible) set_progress_bar_value(objects);
#endif
}
}
static void
add_font(name)
char *name;
{
font *fp;
fp = fonts_ptr;
while (fp && fp->name != name)
fp = fp->next;
if (!fp)
{
fp = new(font);
fp->next = fonts_ptr;
fonts_ptr = fp;
fp->ch_ptr = 0;
fp->name = alloc(strlen(name) + 1);
strcpy(fp->name, name);
}
font_ptr = fp;
}
static void
get_encoding_file(fname)
char *fname;
{
FILE *fp;
char *cname;
code *cp;
int i;
#ifdef __STDC__
char *err1[] =
{"Encoding file read error", 0};
char *err2[] =
{"Unexpected character found in encoding file", 0};
#else
char *err1[ERR_MAX];
char *err2[ERR_MAX];
err1[0] = "Encoding file read error";
err1[1] = 0;
err2[0] = "Unexpected character found in encoding file";
err2[1] = 0;
#endif
fp = cfopen(fname, "r");
codename = alloc(strlen(fname) + 1);
strcpy(codename, fname);
while (fscanf(fp, "%d", &i) > 0)
{
expect("/", fp, fname);
cname = fgets(buffer, BUFFERSIZE, fp);
if (!cname)
errorfn(err1, fp, codename);
cp = new(code);
cp->next = code_ptr;
code_ptr = cp;
cp->code = i;
i = strlen(cname);
cname[i - 1] = 0;
cp->name = alloc(i);
strcpy(cp->name, cname);
}
if (getc(fp) != EOF)
errorfn(err2, fp, codename);
}
static void
change_encoding_vector(name)
char *name;
{
code *cp;
if (codename && !strcmp(codename, name))
return;
if (codename)
{
free(codename);
while (code_ptr)
{
cp = code_ptr;
free(cp->name);
code_ptr = code_ptr->next;
free(cp);
}
}
get_encoding_file(name);
}
static char *
get_com()
{
int nl, c;
char *p, *b;
nl = 0;
while (c = getc(fp), isspace(c))
if (c == '\n')
if (nl)
return (char *) 0;
else
++nl;
if (c == EOF)
return (char *) 0;
ungetc(c, fp);
p = b = get_ident(fp, ifname);
while (*p)
*p = toupper(*p), p++;
return b;
}
void
get_orient()
{
xyz_axes *matp;
#ifdef __STDC__
char *err[] =
{"Null vector", 0};
#else
char *err[ERR_MAX];
err[0] = "Null vector";
err[1] = 0;
#endif
orient_ptr = newa(xyz_axes, 2);
get_vector(&orient_ptr->x_v);
if (!vnormalize(&orient_ptr->x_v))
errorfn(err, fp, ifname);
get_vector(&orient_ptr->y_v);
if (!vnormalize(&orient_ptr->y_v))
errorfn(err, fp, ifname);
get_vector(&orient_ptr->z_v);
if (!vnormalize(&orient_ptr->z_v))
errorfn(err, fp, ifname);
matp = orient_ptr + 1;
if (!vinvmat(&orient_ptr->x_v, &orient_ptr->y_v, &orient_ptr->z_v,
&matp->x_v, &matp->y_v, &matp->z_v))
err[0] = "Linear dependent vectors", errorfn(err, fp, ifname);
}
void
get_pp_obj(fptr)
file_ptr fptr;
{
char *cp, *com;
#ifdef __STDC__
char *err1[] =
{"Undefined ", 0, 0};
char *err2[] =
{"Invalid command", 0};
#else
char *err1[ERR_MAX];
char *err2[ERR_MAX];
err1[0] = "Undefined ";
err1[1] = 0;
err1[2] = 0;
err2[0] = "Invalid command";
err2[1] = 0;
#endif
#ifdef THINK_C
/* On the mac, we change the status text to show we're reading text objects */
if (status_dialog_visible)
set_status_text("\pReading 3D Text Objects…");
#endif
fp = fptr;
while (com = get_com())
{
if (!strcmp(com, "ORIENTATION"))
{
get_orient();
} else if (!strcmp(com, "SCALE"))
{
size_ptr = new(xyz_struct);
get_vector(size_ptr);
} else if (!strcmp(com, "SPACING"))
{
space = get_real(fp, ifname);
} else if (!strcmp(com, "FONT"))
{
cp = get_ident(fp, ifname);
add_font(cp);
} else if (!strcmp(com, "ENCODING"))
{
cp = get_ident(fp, ifname);
change_encoding_vector(cp);
} else if (!strcmp(com, "AT"))
{
if (!orient_ptr)
err1[1] = "ORIENTATION";
else if (!size_ptr)
err1[1] = "SCALE";
else if (space == NULSP)
err1[1] = "SPACING";
else if (!font_ptr)
err1[1] = "FONT";
else if (!code_ptr)
err1[1] = "ENCODING";
if (err1[1])
errorfn(err1, fp, ifname);
get_at_text();
} else
errorfn(err2, fp, ifname);
}
#ifdef THINK_C
/* On the mac, we change the status text to show we're reading objects again */
if (status_dialog_visible)
set_status_text("\pReading Objects…");
#endif
}
static void
free_tables()
{
font *fp, *fp1;
character *chp, *chp1;
fp = fonts_ptr;
while (fp)
{
free(fp->name);
chp = fp->ch_ptr;
while (chp)
{
free(chp->name);
chp1 = chp;
chp = chp->next;
free(chp1);
}
fp1 = fp;
fp = fp->next;
free(fp1);
}
}
void
end_pp_get()
{
free_tables();
}
static int
intersect_line(arr, pos, dir, p0, p1, lim)
real **arr;
xy_ptr pos, dir, p0, p1;
real lim;
{
real a, b, c, d, e, f, t, det;
static real dist[2];
a = dir->x;
c = dir->y;
b = p0->x - p1->x;
d = p0->y - p1->y;
det = a * d - b * c;
if (fabs(det) < TINY)
return 0;
e = p0->x - pos->x;
f = p0->y - pos->y;
t = (a * f - c * e) / det;
if (t < 0.0 || t >= 1.0)
return 0;
dist[0] = (e * d - f * b) / det;
dist[1] = t;
*arr = dist;
return 1;
}
static int
intersect_cubic(arr, pos, dir, p0, p1, p2, p3, lim)
real **arr;
xy_ptr pos, dir, p0, p1, p2, p3;
real lim;
{
static real x[6];
real p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y;
real x0, y0, x1, y1, x2, y2, x3, y3;
real ax, ay, bx, by, cx, cy;
real a, b, c, d, p, q, delta;
real t1, t2, t3;
real rx, ry, vx, vy;
real sqrd, m, tt;
int numint, i;
rx = pos->x;
ry = pos->y;
vx = dir->x;
vy = dir->y;
cx = 3.0 * (p1->x - p0->x);
cy = 3.0 * (p1->y - p0->y);
bx = 3.0 * (p2->x - p1->x) - cx;
by = 3.0 * (p2->y - p1->y) - cy;
ax = p3->x - p0->x - cx - bx;
ay = p3->y - p0->y - cy - by;
a = (vy * ax - vx * ay) * 3.0;
b = vy * bx - vx * by;
c = vy * cx - vx * cy;
d = vy * (p0->x - rx) - vx * (p0->y - ry);
if (fabs(a) < TINY)
if (fabs(b) < TINY)
if (fabs(c) < TINY)
numint = 0;
else
{
x[1] = t1 = -d / c;
if (t1 >= 0.0 && t1 < 1.0)
numint = 1;
else
numint = 0;
}
else
{
real b1;
b1 = c / 2.0 / b;
delta = b1 * b1 - d / b;
if (delta > 0.0)
{
numint = 0;
for (i = -1; i < 2; i += 2)
{
t1 = -b1 + i * sqrt(delta);
if (t1 >= 0.0 && t1 < 1.0)
{
x[2 * numint + 1] = t1;
++numint;
}
}
} else
numint = 0;
}
else
{
b /= a;
c /= a;
d /= a;
if (b > 0.0 && c > 0.0 && d > 0.0)
return 0.0;
if ((d > 0) == (1.0 + 3 * (b + c + d) > 0))
if ((c > 0.0) != (1 + 2 * b + c > 0.0))
if ((d > 0.0) == (c > 0.0))
return 0.0;
else;
else if (b < -1.0 || b > 0.0)
return 0.0;
else;
p = 3 * (c - b * b);
q = b * (2 * b * b - 3 * c) + 3 * d;
delta = q * q / 4 + p * p * p / 27;
if (delta >= TINY)
{
real b1, b2;
sqrd = sqrt(delta);
b1 = -q / 2.0 + sqrd;
b2 = -q / 2.0 - sqrd;
t1 = (b1 > 0.0 ? 1.0 : -1.0) * pow(fabs(b1), (double) 1.0 / 3.0) +
(b2 > 0.0 ? 1.0 : -1.0) * pow(fabs(b2), (double) 1.0 / 3.0) - b;
if (t1 >= 0.0 && t1 < 1.0)
{
x[1] = t1;
numint = 1;
} else
numint = 0;
} else
{
real arg;
m = sqrt(-p / 3.0);
arg = -q / (2 * m * m * m);
if (arg < -1.0)
arg = -1.0;
else if (arg > 1.0)
arg = 1.0;
tt = acos(arg);
numint = 0;
for (i = 0; i < 3; i++)
{
t1 = 2 * m * cos((tt + 2 * M_PI * i) / 3.0) - b;
if (t1 >= 0.0 && t1 < 1.0)
{
x[2 * numint + 1] = t1;
++numint;
}
}
}
}
for (i = 0; i < numint; i++)
{
t1 = x[2 * i + 1];
t2 = t1 * t1;
t3 = t2 * t1;
x[2 * i] = fabs(vx) > fabs(vy) ?
(ax * t3 + bx * t2 + cx * t1 + p0->x - rx) / vx :
(ay * t3 + by * t2 + cy * t1 + p0->y - ry) / vy;
}
*arr = x;
return numint;
}
real
intersect_pp_obj(point_ptr, dir_ptr, bmin_ptr, bmax_ptr, desc_ptr)
xyz_ptr point_ptr, dir_ptr, bmin_ptr, bmax_ptr;
void_ptr desc_ptr;
{
xyz_struct point, pos, dir;
prism *pp;
prismdsc *pdp;
int ncc, nc, cc, c;
ccurve *cca;
curve *ca;
real dist, inf, sup, in;
real distwin;
real tintm0;
int nintlt0, nintltinf, nintwingt0, icur;
int ccim0, cim0;
int top_down, i;
real *arr;
real tmp;
nintlt0 = nintltinf = nintwingt0 = 0;
pp = (prism *) desc_ptr;
pdp = pp->prismdsc_ptr;
vsub(&point, point_ptr, &pp->position);
vtransf(&pos, pp->orient_ptr + 1, &point);
vtransf(&dir, pp->orient_ptr + 1, dir_ptr);
pos.x /= pp->size_ptr->x;
pos.y /= pp->size_ptr->y;
dir.x /= pp->size_ptr->x;
dir.y /= pp->size_ptr->y;
if (fabs(dir.z) < TINY)
{
if (pos.z <= 0.0 || pos.z >= pp->size_ptr->z)
return 0.0;
else
inf = -BIG, sup = BIG;
} else
{
inf = -pos.z / dir.z;
sup = (pp->size_ptr->z - pos.z) / dir.z;
if (inf > sup)
tmp = inf, inf = sup, sup = tmp;
}
ncc = pdp->n;
cca = pdp->ccurve_arr;
for (cc = 0; cc < ncc; cc++)
{
nc = cca[cc].n;
ca = cca[cc].curve_arr;
for (c = 0; c < nc; c++)
{
if (ca[c].t == 1)
icur = intersect_line(&arr, (xy_ptr) & pos, (xy_ptr) & dir,
&ca[c].p[0], &ca[c + 1].p[0], sup);
else
icur = intersect_cubic(&arr, (xy_ptr) & pos, (xy_ptr) & dir,
&ca[c].p[0], &ca[c].p[1], &ca[c].p[2],
&ca[c + 1].p[0], sup);
for (i = 0; i < icur; i++)
{
dist = arr[2 * i];
if (dist < 0.0)
++nintlt0;
if (dist < inf)
++nintltinf;
else if (dist > 0.0 && dist < sup)
{
++nintwingt0;
sup = dist;
tintm0 = arr[2 * i + 1];
ccim0 = cc;
cim0 = c;
}
}
}
}
if (sup < 0.0)
return 0.0;
if (!(nintlt0 % 2) || pos.z < 0.0 || pos.z > pp->size_ptr->z)
{
pp->enter = 1;
if (inf > 0.0)
{
if (nintltinf % 2)
top_down = 1, dist = inf;
else if (nintwingt0)
top_down = 0, dist = sup;
else
return 0.0;
} else
{
if (nintwingt0)
top_down = 0, dist = sup;
else
return 0.0;
}
} else
{
pp->enter = 0;
dist = sup;
if (nintwingt0)
top_down = 0;
else
top_down = 1;
}
if (top_down)
pp->ccint = -1;
else
{
pp->ccint = ccim0;
pp->cint = cim0;
pp->tint = tintm0;
}
pp->dirint = dir;
return dist;
}
void
normal_pp_obj(pos_ptr, desc_ptr, normal_ptr)
xyz_ptr pos_ptr;
void_ptr desc_ptr;
xyz_ptr normal_ptr;
{
real x0, y0, x1, y1, x2, y2, x3, y3;
real ax, ay, bx, by, cx, cy;
real t, xl, yl;
prism *pp;
prismdsc *pdp;
int cc, c;
ccurve *cca;
curve *ca;
xyz_struct n;
pp = (prism *) desc_ptr;
pdp = pp->prismdsc_ptr;
cc = pp->ccint;
c = pp->cint;
cca = pdp->ccurve_arr;
ca = cca[cc].curve_arr;
if (pp->ccint < 0)
{
n.x = n.y = 0.0;
n.z = 1.0;
} else if (ca[c].t == 1)
{
n.x = ca[c + 1].p[0].y - ca[c].p[0].y;
n.y = ca[c].p[0].x - ca[c + 1].p[0].x;
n.z = 0.0;
n.x /= pp->size_ptr->x;
n.y /= pp->size_ptr->y;
} else
{
x0 = ca[c].p[0].x;
y0 = ca[c].p[0].y;
x1 = ca[c].p[1].x;
y1 = ca[c].p[1].y;
x2 = ca[c].p[2].x;
y2 = ca[c].p[2].y;
x3 = ca[c + 1].p[0].x;
y3 = ca[c + 1].p[0].y;
cx = 3 * (x1 - x0);
cy = 3 * (y1 - y0);
bx = 3 * (x2 - x1) - cx;
by = 3 * (y2 - y1) - cy;
ax = x3 - x0 - cx - bx;
ay = y3 - y0 - cy - by;
t = pp->tint;
xl = 3 * ax * t * t + 2 * bx * t + cx;
yl = 3 * ay * t * t + 2 * by * t + cy;
n.x = yl;
n.y = -xl;
n.z = 0.0;
n.x /= pp->size_ptr->x;
n.y /= pp->size_ptr->y;
}
if ((vpint(&pp->dirint, &n) > 0.0) ^ !pp->enter)
n.x = -n.x, n.y = -n.y, n.z = -n.z;
vtransf(normal_ptr, pp->orient_ptr, &n);
}